package com.soundplus.app.shp04.DeviceConnectMgr;

import static com.example.sppmode.Common.DataConfig.CONN_PROTOCOL_TYPE_NONE;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.example.sppmode.Common.DataConfig;
import com.example.sppmode.DeviceConnectMgr.SPPEventListener;
import com.example.sppmode.DeviceConnectMgr.SppConnMgr;
import com.example.sppmode.Common.MyByteQueue;
import com.example.sppmode.Common.Utils;
import com.example.sppmode.DataProtocol.CommandAnalyzeResult;
import com.example.sppmode.DataProtocol.CommandDataAnalyze;
import com.example.sppmode.DataProtocol.CommandInfo;

public class DevConnService extends Service {
    private static final String TAG = "DevConnService";



    public static final int MSGID_ANALYZE_RECV_DATA = 1;



    private Context context;
    private MyHandler myHandler;
    private final MyBinder myBinder = new MyBinder();
    private LocalBroadcastManager localBroadcastManager = null;

    private BleConnMgr LeConnMgr;
    private SppConnMgr sppConnMgr;
    private int connProtocolType = CONN_PROTOCOL_TYPE_NONE;
    private MyByteQueue recvQueue = new MyByteQueue("recvQueue", 1024 * 2);
    private int devConnStatus = DataConfig.STATE_DISCONNECTED;
    private DevConnEventListener devConnEventListener = null;


    @Override
    public void onCreate() {
        super.onCreate();

        context = this;
        myHandler = new MyHandler(context, getMainLooper());
        LeConnMgr = new BleConnMgr(context, bleEventListener);
        sppConnMgr = new SppConnMgr(context, sppEventListener);
        localBroadcastManager = LocalBroadcastManager.getInstance(context);

        BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {

            }
        };

    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return myBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        LeConnMgr.destroy();
        sppConnMgr.destory();
    }

    public class MyBinder extends Binder {
        public DevConnService getService() {
            return DevConnService.this;
        }
    }

    private class MyHandler extends Handler {
        Context context;
        Looper looper;

        public MyHandler(Context context, Looper looper) {
            super(looper);
            this.context = context;
            this.looper = looper;
        }

        @Override
        public void handleMessage(Message msg) {
            if (msg.what == MSGID_ANALYZE_RECV_DATA) {
                analyzeRecvData();
            }
        }
    }

    private BleEventListener bleEventListener = new BleEventListener() {

        @Override
        public void onConnStatusChanged(int status) {
            if (status == BleConnMgr.BLE_CONNECTED)
                devConnStatus = DataConfig.STATE_CONNECTED;
            else if (status == BleConnMgr.BLE_CONNECTING)
                devConnStatus = DataConfig.STATE_CONNECTING;
            else
                devConnStatus = DataConfig.STATE_DISCONNECTED;

            if (devConnEventListener != null) {
                Log.d(TAG, "onConnStatusChanged devConnStatus=" + devConnStatus);
                devConnEventListener.onConnStatusChanged(devConnStatus);
            }
        }

        @Override
        public void onDataReceived(byte[] data) {
            Log.d(TAG, "onDataReceived");
            Log.d(TAG, "ble recv frameData:" + Utils.convertByteArray2HexStr(data, data.length));
            if (data == null || data.length == 0)
                return;

            boolean hasDeal = false;

            /* 如果已经被监听端处理数据，无需把数据加入队列并解析指令。 */
            if (!hasDeal) {
                recvQueue.enQueue(data);
                myHandler.sendMessage(myHandler.obtainMessage(MSGID_ANALYZE_RECV_DATA));
            }
        }
    };

    private SPPEventListener sppEventListener = new SPPEventListener() {
        @Override
        public void onConnStatusChanged(int status) {
            Log.d(TAG, "onConnStatusChanged status=" + status);
            if (status == SppConnMgr.SPP_CONNECTED)
                devConnStatus = DataConfig.STATE_CONNECTED;
            else if (status == SppConnMgr.SPP_DISCONNECTED)
                devConnStatus = DataConfig.STATE_DISCONNECTED;

            if (devConnEventListener != null) {
                devConnEventListener.onConnStatusChanged(devConnStatus);
            }
        }

        @Override
        public void onRecvData(byte[] data, int dataLen) {
            Log.d(TAG, "onRecvData, dataLen=" + dataLen);
            if (data == null || data.length == 0)
                return;
            Log.d(TAG, "spp recv frameData:" + Utils.convertByteArray2HexStr(data, dataLen > 32 ? 32 : dataLen));

            byte[] recvData = new byte[dataLen];
            System.arraycopy(data, 0, recvData, 0, dataLen);

            boolean hasDeal = false;

            /** 如果已经被监听端处理数据，无需把数据加入队列并解析指令。 */
            if (!hasDeal) {
                recvQueue.enQueue(recvData);
                myHandler.sendMessage(myHandler.obtainMessage(MSGID_ANALYZE_RECV_DATA));
            }
        }
    };

    public void addDevConnEventListener(DevConnEventListener listener) {
        devConnEventListener = listener;
    }

    public void removeDevConnEventListener(DevConnEventListener listener) {
        devConnEventListener = null;
    }

    public void clearDevConnEventListener() {
        devConnEventListener = null;
    }


    public void connectDevice(int devType, String addr) {
        Log.d(TAG, "connectDevice，devType=" + devType + ", addr=" + addr);
        this.connProtocolType = devType;
        if (devType == DataConfig.CONN_PROTOCOL_TYPE_BLE) {
            LeConnMgr.connectDevice(addr);
        } else if (devType == DataConfig.CONN_PROTOCOL_TYPE_SPP) {
            sppConnMgr.connectDevice(addr); //spp连接设备
        }
    }

    public void disconnectDevice() {
        if (connProtocolType == DataConfig.CONN_PROTOCOL_TYPE_BLE) {
            LeConnMgr.disconnectDevice();
        }
    }

    public int getDevConnectStatus() {
        return devConnStatus;
    }

    public void sendCommand(CommandInfo cmdInfo) {
        Log.d(TAG, "sendCommand");
        if (cmdInfo == null) {
            Log.d(TAG, "cmdInfo == null, return");
            return;
        }
        if (devConnStatus != DataConfig.STATE_CONNECTED) {
            Log.d(TAG, "devConnStatus(" + devConnStatus + ") != STATE_CONNECTED, return");
            return;
        }

        cmdInfo.setFrom(CommandInfo.DEVICE_APP);
        byte[] framData = CommandDataAnalyze.packFrameData(cmdInfo);
        if (connProtocolType == DataConfig.CONN_PROTOCOL_TYPE_BLE) {
            LeConnMgr.sendData(framData);
        } else if (connProtocolType == DataConfig.CONN_PROTOCOL_TYPE_SPP) {
            sppConnMgr.sendData(framData, framData.length);
        }
    }

    private boolean analyzeRecvData() {
        Log.d(TAG, "analyzeRecvData");

        CommandAnalyzeResult analyzeResult = CommandDataAnalyze.analyzeFrameData(recvQueue);
        if (analyzeResult.getErrCode() == CommandInfo.ERROR_CODE_INVALID_WAIT_MORE) {
            return true;
        }

        CommandInfo commandInfo = analyzeResult.getCommandInfo();
        if(commandInfo == null) {
            if (recvQueue.length() > 0) {
                recvQueue.clear();
            }
            return false;
        }

        CommandDataAnalyze.dealCommandData(commandInfo);

        if (devConnEventListener != null) {
            Log.d(TAG, "analyzeRecvData devConnEventListener");
            devConnEventListener.onCommandReceived(commandInfo);
        }

        if (recvQueue.length() > 0) {
            myHandler.sendMessageDelayed(myHandler.obtainMessage(MSGID_ANALYZE_RECV_DATA), 500);
        }
        return true;
    }
}
